From ColdFusion 11 onwards, you may use THIS.DATASOURCES in Application.cfc – or, equivalenty, the Datasources attribute in Application.cfm – to create a datasource. ( Application.cfc is the recommended file to use, so we shall not consider Application.cfm in what follows. )
THIS.DATASOURCES is a struct. So, how do know which keys it contains? The purpose of this blog post is to answer that question. .
Datasource creation in ColdFusion
To run a query in ColdFusion you have to define a datasource. The datasource is an object that contains connection and database properties. These are the properties which enable the query to execute on a specific local or remote database.
ColdFusion offers you 2 main ways to create a datasource:
1) via the ColdFusion Administrator;
2) via the THIS.DATASOURCES instance variable in Application.cfc .
The most common way is to define the datasource in the Datasource page of the ColdFusion Administrator. There you are provided with form fields to fill. (See pictures below.) This is an indispensable ColdFusion feature which has been there since the early ColdFusion versions.
ColdFusion 11 introduced the second way to define a datasource, namely, via THIS.DATASOURCES in Application.cfc. The datasources defined using THIS.DATASOURCES are specific to the application, unlike the datasources created in the Administrator, which are available to every application server-wide.
An example to show the THIS.DATASOURCES syntax:
this.datasources := {
dsn1 : { driver: “MSSQLServer”,
urlmap: {database: “testMSSQL”, host: “localhostMSSQL2008”},
username: “sa”,
password: “xxxxxxxx” },
dsn2: { username: “root”,
password: “xxxxxxxx”,
driver: “MySQL5”,
class: “com.mysql.jdbc.Driver”,
name:”bkbk_cf_mysql_db”,
url: “jdbc:mysql://127.0.0.1:3306/bkbk_cf_mysql_db?serverTimezone: Europe/London” },
dsn3:: { username: “sa”,
password: “xxxxxxx”
driver: “MSSQLServer”,
url:: “jdbc:macromedia:sqlserver://localhostMSSQL2008”,
urlmap: {database: “myMSSQL”, sendStringParametersAsUnicode: false, maxPooledStatements: 1000},
timeout: 0}
};
Hence THIS.DATASOURCES is a struct of structs. Its keys are the names of the datasources created for the application.
You will have noticed that this method requires you to know beforehand which properties to use in defining each datasource. This is in contrast to the ColdFusion Administrator method, where ColdFusion provides the required properties as form fields.
The example shows you some crucial keys:
Class
Driver
Name
Password
Username
Timeout
Url
UrlMap
So, how do know the names of the rest of the keys? How could you have guessed that a key, such as UrlMap, is itself a struct? What is its full set of keys?
The answers follow.
The complete list of keys of any arbitrary datasource, This.datasources[“myDSN”], is:
Alter
Blob_Buffer
Buffer
Class
Clientinfo
Create
Delete
Description
Disable
Disable_Autogenkeys
Disable_Blob
Disable_Clob
Driver
Drop
Grant
Insert
Interval
Isj2ee
Login_Timeout
Name
Password
Pooling
Revoke
Select
Storedproc
Timeout
Update
Url
Urlmap
Username
Validateconnection
Validationquery
To obtain the full description of the keys (structure, datatype, default value), run the following code as a CFM page:
<!— Login into Coldfusion Administrator. —>
<cfset createObject(“component”,”cfide.adminapi.administrator”).login(“your_cf_admin_password”)>
<!— Instantiate the data source object. —>
<cfset datasourceObject = createObject(“component”,”cfide.adminapi.datasource”)>
<!— Get a structure containing all the data sources —>
<cfset datasources = datasourceObject.getDatasources()>
<!— <cfdump var=”#datasources#” label=”All available data sources”> —>
<!— Get a structure containing the details of the cfArtGallery datasource —>
<cfset cfArtGalleryDatasource = datasources.cfartgallery>
<cfdump var=”#cfArtGalleryDatasource#” label=”cfArtGallery Datasource”>
The result is:
cfArtGallery Datasource – struct | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
CLASS | org.apache.derby.jdbc.EmbeddedDriver | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DRIVER | Apache Derby Embedded | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ISJ2EE | NO | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
NAME | cfartgallery | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
alter | YES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
blob_buffer | 64000 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buffer | 64000 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
clientinfo |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
create | YES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
delete | YES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
description | [empty string] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
disable | NO | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
disable_autogenkeys | NO | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
disable_blob | YES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
disable_clob | YES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
drop | YES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
grant | YES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
insert | YES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
interval | 420 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
login_timeout | 30 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
password | [empty string] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pooling | YES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
revoke | YES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
select | YES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
storedproc | YES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
timeout | 1200 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
update | YES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
url | jdbcerby:C:ColdFusion2021cfusiondbartgallery;create=false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
urlmap |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
username | [empty string] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
validateConnection | NO | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
validationQuery | [empty string] |
I have this working with Adobe ColdFusion 2021, but am failing to get this working for 2023 (in my local dev environment). For what it’s worth, I could not get the CFAdmin API calls to authenticate until I went into the CFAdmin and completely disabled the security. Even after adding a new Admin User, and granting them full-rights on everything that I could, I was getting security errors when trying to access the datasources. That is, until I completely disabled the security.
Once I did that, I could see the datasource details. But, unfortunately, trying to replicate them into my Application.cfc code doesn’t work. Can anyone confirm that this approach still works in 2023?
So, here’s my proof-of-concept. I went into the CFAdmin and I created a datasource called test. Then, I created a stand-alone CF app that runs this simple query using this.datasource=”test”:
<cfquery name=”results”>
SELECT 1;
</cfquery>
This works. Then, I tried to programmatically create a new datasource called test2 simply by grabbing the CFAdmin results of the datasource and pointing test2 at test:
this.cfadmin = createObject( “component”, “cfide.adminapi.administrator” );
this.cfadmin.login( “” ); // I’ve completely disabled security to get this working.
this.datasources = createObject( “component”, “cfide.adminapi.datasource” )
.getDatasources()
;
// I know there is a datasource called “test”, created via the CFAdmin. Let’s
// duplicate it’s configuration to see if we can consume it.
this.datasources[ “test2” ] = this.datasources[ “test” ];
this.datasource = “test2”;
When I try to run the same query, I get the error:
Datasource test2 could not be found.
Should this approach work? Actually, I will try going back to 2021 and see if this approach works.
Ok, I tried to boil this down the most simple, hard-coded values. I have this in my Application.cfc:
this.datasources = { “test2”: {
username: “root”,
password: “password”,
driver: “MySQL”,
class: “com.mysql.cj.jdbc.Driver”,
url: “jdbc:mysql://mysql:3306/bennadel”
} };
this.datasource = “test2”;
When I build my Docker container using FROM ortussolutions/commandbox:adobe2021 this code works fine. When I build it using `FROM ortussolutions/commandbox:adobe2023` this code breaks and says it cannot find the datasource.
Maybe it’s something in the OrtusSolutions Image; or it’s a breaking change in the ColdFusion runtime?
Charlie, thanks for the suggestion.
This.Datasources documentation Feature Request: https://tracker.adobe.com/#/view/CF-4212922
You must be logged in to post a comment.